package com.example.demo.generator.scaffold.util;

import com.example.demo.generator.scaffold.model.TemplateContext;
import com.example.demo.generator.scaffold.model.ScaffoldOptions;
import com.example.demo.generator.codegen.model.FieldInfo;

import java.util.List;

/**
 * 提供脚手架产物命名相关的辅助方法，确保模板与输出路径使用一致的约定。
 */
public final class ScaffoldNameUtils {

    private ScaffoldNameUtils() {
    }

    public static String deriveApplicationClassName(TemplateContext context) {
        String candidate = resolveModuleCandidate(context);
        String base = toPascalCase(candidate, "Demo");
        return base + "Application";
    }

    public static String deriveArtifactId(TemplateContext context) {
        String candidate = resolveModuleCandidate(context);
        String normalized = toKebabCase(candidate, "demo-module");
        return normalized + "-service";
    }

    public static String deriveProjectName(TemplateContext context) {
        String candidate = resolveModuleCandidate(context);
        return toKebabCase(candidate, "blockasset-module");
    }

    public static String deriveFrontendProjectName(TemplateContext context) {
        String projectName = deriveProjectName(context);
        ScaffoldOptions.FrontendFramework framework = context.getFrontendFramework();
        String suffix = framework == ScaffoldOptions.FrontendFramework.VUE ? "vue" : "react";
        return projectName + "-web-" + suffix;
    }

    public static String deriveDatasourceName(TemplateContext context) {
        String candidate = resolveModuleCandidate(context);
        return toAlphanumeric(candidate, "blockasset");
    }

    public static String deriveFrontendManagementBaseName(TemplateContext context) {
        String modulePascal = toPascalCase(resolveModuleCandidate(context), "Module");
        if (modulePascal.endsWith("Management")) {
            return modulePascal;
        }
        if (modulePascal.endsWith("Module")) {
            modulePascal = modulePascal.substring(0, modulePascal.length() - "Module".length());
        }
        return modulePascal + "Management";
    }

    public static String deriveFrontendReactPageComponentName(TemplateContext context) {
        return deriveFrontendManagementBaseName(context) + "Page";
    }

    public static String deriveFrontendVueViewComponentName(TemplateContext context) {
        return deriveFrontendManagementBaseName(context) + "View";
    }

    public static String deriveFrontendRouteSegment(TemplateContext context) {
        String base = deriveFrontendManagementBaseName(context);
        return toKebabCase(base, "module-management");
    }

    public static String deriveApiBasePath(TemplateContext context) {
        String explicit = context.getOptions().getApiPrefix();
        if (explicit != null) {
            String trimmed = explicit.trim().replaceAll("^/+", "").replaceAll("/+$", "");
            if (!trimmed.isEmpty()) {
                String normalized = toKebabCase(trimmed, trimmed);
                if (!normalized.isBlank()) {
                    return normalized;
                }
            }
        }
        String candidate = context.getClassInfo() != null ? context.getClassInfo().getClassName() : resolveModuleCandidate(context);
        String normalized = toKebabCase(candidate, "module");
        if (!normalized.endsWith("s")) {
            normalized = normalized + "s";
        }
        return normalized;
    }

    public static String resolveOperationVerb(String httpMethod) {
        if (httpMethod == null) {
            return "操作";
        }
        String method = httpMethod.trim().toUpperCase();
        switch (method) {
            case "GET":
                return "查询";
            case "POST":
                return "创建";
            case "PUT":
            case "PATCH":
                return "更新";
            case "DELETE":
                return "删除";
            default:
                return "操作";
        }
    }

    public static String resolvePrimaryKeyAlias(TemplateContext context) {
        List<String> primaryColumns = context.getClassInfo().getPrimaryKeyColumns();
        if (primaryColumns.isEmpty()) {
            return "id";
        }
        return primaryColumns.get(0);
    }

    public static String resolvePrimaryKeyFieldName(TemplateContext context) {
        List<String> primaryColumns = context.getClassInfo().getPrimaryKeyColumns();
        if (primaryColumns.isEmpty()) {
            return context.getClassInfo().getFieldList().isEmpty()
                    ? "id"
                    : context.getClassInfo().getFieldList().get(0).getFieldName();
        }
        return context.getClassInfo().getFieldList().stream()
                .filter(field -> primaryColumns.stream().anyMatch(column -> column.equalsIgnoreCase(field.getColumnName())))
                .map(FieldInfo::getFieldName)
                .findFirst()
                .orElse(context.getClassInfo().getFieldList().isEmpty()
                        ? "id"
                        : context.getClassInfo().getFieldList().get(0).getFieldName());
    }

    public static String resolvePrimaryKeyFieldType(TemplateContext context) {
        String fieldName = resolvePrimaryKeyFieldName(context);
        return context.getClassInfo().getFieldList().stream()
                .filter(field -> field.getFieldName().equals(fieldName))
                .map(field -> field.getFieldClass() != null ? field.getFieldClass() : "Long")
                .findFirst()
                .orElse("Long");
    }

    private static String resolveModuleCandidate(TemplateContext context) {
        String candidate = context.getModuleName();
        if (candidate == null || candidate.isBlank()) {
            candidate = context.getModuleSimpleName();
        }
        if ((candidate == null || candidate.isBlank()) && context.getClassInfo() != null) {
            candidate = context.getClassInfo().getClassName();
        }
        return candidate;
    }

    private static String toPascalCase(String value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        String trimmed = value.trim();
        if (trimmed.isEmpty()) {
            return defaultValue;
        }
        String[] parts = trimmed.replaceAll("[^a-zA-Z0-9]", " ").split("\\s+");
        StringBuilder builder = new StringBuilder();
        for (String part : parts) {
            if (part.isEmpty()) {
                continue;
            }
            builder.append(Character.toUpperCase(part.charAt(0)));
            if (part.length() > 1) {
                builder.append(part.substring(1).toLowerCase());
            }
        }
        if (builder.length() == 0) {
            return defaultValue;
        }
        return builder.toString();
    }

    private static String toKebabCase(String value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        String trimmed = value.trim();
        if (trimmed.isEmpty()) {
            return defaultValue;
        }
        String withWordBoundaries = trimmed
                .replaceAll("([a-z0-9])([A-Z])", "$1-$2")
                .replaceAll("([A-Z]+)([A-Z][a-z])", "$1-$2");
        String normalized = withWordBoundaries
                .replaceAll("[^a-zA-Z0-9]+", "-")
                .replaceAll("-+", "-")
                .replaceAll("^-+", "")
                .replaceAll("-+$", "")
                .toLowerCase();
        if (normalized.isBlank()) {
            return defaultValue;
        }
        return normalized;
    }

    private static String toAlphanumeric(String value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        String normalized = value.trim().replaceAll("[^a-zA-Z0-9]", "");
        if (normalized.isEmpty()) {
            return defaultValue;
        }
        return normalized.toLowerCase();
    }

    public static String humanizeName(String value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        String trimmed = value.trim();
        if (trimmed.isEmpty()) {
            return defaultValue;
        }
        // 对已经是中文或包含非 ASCII 字符的场景，保留原样仅压缩空白
        if (trimmed.codePoints().anyMatch(code -> Character.UnicodeScript.of(code) == Character.UnicodeScript.HAN)) {
            return trimmed.replaceAll("\\s+", " ");
        }
        String withSpaces = trimmed
                .replaceAll("([A-Z]+)([A-Z][a-z])", "$1 $2")
                .replaceAll("([a-z0-9])([A-Z])", "$1 $2")
                .replaceAll("[_-]+", " ")
                .replaceAll("\\s+", " ");
        if (withSpaces.isEmpty()) {
            return defaultValue;
        }
        String[] parts = withSpaces.split(" ");
        StringBuilder builder = new StringBuilder();
        for (String part : parts) {
            if (part.isEmpty()) {
                continue;
            }
            if (builder.length() > 0) {
                builder.append(' ');
            }
            builder.append(Character.toUpperCase(part.charAt(0)));
            if (part.length() > 1) {
                builder.append(part.substring(1).toLowerCase());
            }
        }
        if (builder.length() == 0) {
            return defaultValue;
        }
        return builder.toString();
    }
}

